package com.applang.components;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;
import java.util.regex.Pattern;
import javax.swing.AbstractButton;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import org.gjt.sp.jedit.BeanShell;
import org.gjt.sp.jedit.bsh.NameSpace;
import org.gjt.sp.jedit.gui.RolloverButton;
import org.gjt.sp.jedit.textarea.TextArea;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import android.util.Log;
import com.applang.Util;
import com.applang.SwingUtil.UIFunction;
import com.applang.berichtsheft.BerichtsheftApp;
import com.applang.berichtsheft.plugin.BerichtsheftPlugin;
import static com.applang.Util.*;
import static com.applang.Util2.*;
import static com.applang.SwingUtil.*;
@SuppressWarnings("rawtypes")
public class ScriptManager extends ManagerBase<Element>
{
private static final String TAG = ScriptManager.class.getSimpleName();
public static String flavorSelector(Object name) {
return String.format("/FLAVOR[@name='%s']", name);
}
public static String projectionSelector(Object table) {
return String.format("/PROJECTION[@table='%s']", table);
}
public static boolean setProjectionDefault(Object flavor, String tableName, ValMap map) {
if (ProfileManager.transportsLoaded()) {
String xpath = ProfileManager.transportsSelector + flavorSelector(flavor);
Element element = selectElement(ProfileManager.transports, xpath);
if (element != null && notNullOrEmpty(tableName)) {
Element el = ProfileManager.transports.createElement("PROJECTION");
try {
BidiMultiMap projection = (BidiMultiMap) map.get("projection");
xmlSerialize(projection, el, null);
el.setAttribute("version", "" + map.get("version"));
el.setAttribute("table", tableName);
} catch (Exception e) {
Log.e(TAG, "setDefaultProjection", e);
return false;
}
NodeList nodes = evaluateXPath(element, "." + projectionSelector(tableName));
if (nodes != null && nodes.getLength() > 0) {
Node node = nodes.item(0);
node.getParentNode().replaceChild(el, node);
}
else
element.appendChild(el);
ProfileManager.saveTransports();
return true;
}
}
return false;
}
public static ValMap getProjectionDefault(Object flavor, String tableName) {
ValMap map = vmap();
if (ProfileManager.transportsLoaded()) {
String xpath = ProfileManager.transportsSelector + flavorSelector(flavor);
Element element = selectElement(ProfileManager.transports, xpath);
if (element != null) {
NodeList nodes = evaluateXPath(element, "." + projectionSelector(tableName));
if (nodes != null && nodes.getLength() > 0) {
element = (Element) nodes.item(0);
try {
map.put("table", tableName);
map.put("version", toInt(-1, element.getAttribute("version")));
map.put("projection", xmlDeserialize(element, null));
} catch (Exception e) {
Log.e(TAG, "getDefaultProjection", e);
}
}
}
}
return map;
}
public static Object doConversion(Object value, String function, String oper, Object...params) {
try {
if (!ProfileManager.transportsLoaded() || nullOrEmpty(function))
return value;
NameSpace tmp = new NameSpace(BeanShell.getNameSpace(), "transport");
tmp.setVariable("value", value);
tmp.setVariable("oper", oper);
Element el = selectElement(ProfileManager.transports, "//FUNCTION[@name='" + function + "']");
if (el == null) {
BerichtsheftPlugin.consoleMessage("berichtsheft.doConversion.message.1", function);
return value;
}
String script = param(el.getTextContent(), 0, params);
return BeanShell.eval(null, tmp, script);
}
catch (Exception e) {
BerichtsheftPlugin.consoleMessage("berichtsheft.doConversion.message.2", function, value);
return null;
}
}
public ScriptManager(final Component parent, Component relative, Object...params) {
String selector = param_String("", 0, params);
this.selector += selector;
this.profile = param(null, 1, params);
String title = param_String("Script editor", 2, params);
final String function = param(null, 3, params);
int behavior = param_Integer(Behavior.MODAL, 4, params);
showDialog(parent, relative,
title,
new UIFunction() {
public Component[] apply(Component comp, Object[] parms) {
final JDialog dlg = (JDialog) comp;
blockDirty(new Job<Void>() {
public void perform(Void t, Object[] params) throws Exception {
createUI(parent, dlg.getContentPane());
}
});
return null;
}
},
new UIFunction() {
public Component[] apply(Component comp, Object[] parms) {
JDialog dlg = (JDialog) comp;
JButton btn = findFirstComponent(dlg.getContentPane(), ACCEPT_BUTTON_KEY);
btn.getRootPane().setDefaultButton(btn);
if (function != null)
setFunction(function);
return null;
}
},
new UIFunction() {
public Component[] apply(Component comp, Object[] parms) {
comboBoxes[0].setSelectedIndex(-1);
return null;
}
},
behavior);
}
public ScriptManager(TextToggle textToggle) {
textArea = textToggle;
}
public JDialog scriptDialog = null;
public void showScriptDialog(Component parent, Component relative,
String title,
int behavior,
Object...params)
{
scriptDialog = showDialog(parent, relative, title,
new UIFunction() {
public Component[] apply(Component comp, Object[] parms) {
final JDialog dlg = (JDialog) comp;
blockDirty(new Job<Void>() {
public void perform(Void t, Object[] params) throws Exception {
comboBoxes = new JComboBox[] {new JComboBox()};
Container container = dlg.getContentPane();
addCenterComponent(textArea.getTextArea(), container);
JToolBar bar = northToolBar(container, BorderLayout.SOUTH);
createButton(bar,
SYNC_BUTTON_KEY,
new ActionListener() {
public void actionPerformed(ActionEvent e) {
textArea.getTextEdit().setText(textArea.getText());
}
});
// installUpdate(bar);
// textArea.setOnTextChanged(new Job<JComponent>() {
// public void perform(JComponent t, Object[] params) throws Exception {
// setDirty(true);
// }
// });
}
});
return null;
}
},
new UIFunction() {
public Component[] apply(Component comp, Object[] parms) {
Util.Job<TextArea> job = param(null, 0, parms);
if (job != null)
try {
job.perform(textArea.getTextArea(), parms);
} catch (Exception e) {
Log.e(TAG, "showScriptDialog", e);
}
return null;
}
},
new UIFunction() {
public Component[] apply(Component comp, Object[] parms) {
JDialog dlg = (JDialog) comp;
AbstractButton btn = findFirstComponent(dlg.getContentPane(), SYNC_BUTTON_KEY);
if (btn != null)
btn.doClick();
scriptDialog = null;
return null;
}
},
behavior,
params);
}
private TextToggle textArea;
private JLabel mess;
private String selector = ProfileManager.transportsSelector;
private String profile = null;
@Override
protected Element select(Object...function) {
if (ProfileManager.transportsLoaded()) {
String xpath = selector;
if (isAvailable(0, function)) {
xpath += "/FUNCTION[@name='" + function[0] + "'";
if (notNullOrEmpty(profile))
xpath += " and @profile='" + profile + "'";
xpath += "]";
}
return selectElement(ProfileManager.transports, xpath);
}
return null;
}
@Override
protected boolean addItem(boolean refresh, Object function) {
if (ProfileManager.transportsLoaded()) {
String body = textArea.getText();
if (notNullOrEmpty(body)) {
Element element = ProfileManager.transports.createElement("FUNCTION");
element.setAttribute("name", stringValueOf(function));
if (notNullOrEmpty(profile))
element.setAttribute("profile", profile);
Element el = ProfileManager.transports.createElement("BODY");
CDATASection cdata = ProfileManager.transports.createCDATASection(body);
el.appendChild(cdata);
element.appendChild(el);
select().appendChild(element);
updateModel(true, true, true, function);
return true;
}
}
return false;
}
@Override
protected boolean removeItem(Object function) {
Element element = select(function);
boolean retval = element != null;
if (retval) {
element.getParentNode().removeChild(element);
updateModel(true, true, false);
}
return retval;
}
@Override
protected void updateItem(boolean accept, Object...params) {
String function = param(null, 0, params);
boolean refresh = function == null;
if (refresh)
function = getFunction();
Element element = select(function);
if (element != null) {
String body = textArea.getText();
if (accept) {
NodeList nodes = evaluateXPath(element, "./BODY/text()");
if (nodes != null && nodes.getLength() > 0) {
Node node = nodes.item(0);
CDATASection cdata = ProfileManager.transports.createCDATASection(body);
node.getParentNode().replaceChild(cdata, node);
updateModel(refresh, true, true);
}
}
else if (refresh)
setFunction(function);
}
}
@SuppressWarnings("unchecked")
private void updateModel(boolean refresh, boolean save, boolean keepSelection, Object...params) {
String function = param(getFunction(), 0, params);
if (ProfileManager.transportsLoaded()) {
if (refresh) {
blockDirty(new Job<Void>() {
public void perform(Void t, Object[] params) throws Exception {
DefaultComboBoxModel model = (DefaultComboBoxModel) comboBoxes[0].getModel();
model.removeAllElements();
NodeList nodes = evaluateXPath(
ProfileManager.transports, selector + "/FUNCTION");
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
model.addElement(element.getAttribute("name"));
}
comboBoxes[0].setModel(model);
}
});
}
if (save)
ProfileManager.saveTransports();
}
if (!refresh)
return;
if (!keepSelection)
function = getFunction();
setFunction(function);
}
public String getFunction() {
Object item = comboBoxes[0].getSelectedItem();
return stringValueOf(item);
}
public void setFunction(final String function) {
blockDirty(new Job<Void>() {
public void perform(Void t, Object[] params) throws Exception {
comboBoxes[0].getModel().setSelectedItem(function);
String body = "";
Element element = select(function);
if (element != null) {
NodeList nodes = evaluateXPath(element, "./BODY/text()");
if (nodes != null && nodes.getLength() > 0) {
Node node = nodes.item(0);
body = node.getTextContent();
}
}
textArea.setText(body);
}
});
setDirty(false);
}
private void createUI(final Component parent, final Container container) {
comboBoxes = new JComboBox[] {new JComboBox()};
textArea = new TextToggle().createBufferedTextArea("beanshell", "/modes/java.xml");
JToolBar bar = new JToolBar();
container.add(bar, BorderLayout.NORTH);
final RolloverButton btn = createButton(bar,
ACCEPT_BUTTON_KEY,
new ActionListener() {
public void actionPerformed(ActionEvent e) {
save(getItem(), false);
Window window = SwingUtilities.getWindowAncestor(container);
if (window != null)
window.dispose();
}
});
comboBoxes[0].addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent ev) {
if (ev.getStateChange() == ItemEvent.SELECTED) {
String function = getFunction();
if (select(function) != null)
setFunction(function);
else
setDirty(true);
}
else if (ev.getStateChange() == ItemEvent.DESELECTED) {
String item = stringValueOf(ev.getItem());
save(item, false);
}
}
});
comboBoxes[0].setEditable(true);
comboEdit(0).setHorizontalAlignment(JTextField.CENTER);
bar.add(comboBoxes[0]);
comboEdit(0).addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
btn.doClick();
}
}
});
installAddRemove(bar, "function");
installUpdate(bar);
final RolloverButton test = new RolloverButton();
test.setText("Test");
test.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
testThis(parent, container, comboEdit(0).getText());
}
});
test.setEnabled(findAllIn(selector, Pattern.compile("/")).length < 2);
bar.add(test);
textArea.setOnTextChanged(new Job<JComponent>() {
public void perform(JComponent t, Object[] params) throws Exception {
setDirty(true);
}
});
container.add(textArea.getUIComponent(), BorderLayout.CENTER);
mess = new JLabel();
mess.setHorizontalAlignment(JTextField.CENTER);
container.add(mess, BorderLayout.SOUTH);
updateModel(true, false, false);
}
String[] keys = { "oper", "type", "value" };
Object[] values = { "push", "TEXT", null };
private void testThis(Component parent, Component relative, final String name) {
mess.setText("");
final DefaultTableModel model = new DefaultTableModel(3, 2) {
@Override
public Object getValueAt(int row, int col) {
if (col == 0)
return keys[row];
else
return values[row];
}
@Override
public void setValueAt(Object aValue, int row, int col) {
if (col == 1)
values[row] = aValue;
}
@Override
public Class<?> getColumnClass(int col) {
if (col == 1) {
if ("push".equals(values[0])) {
if ("INTEGER".equals(values[1]))
return Long.class;
else if ("REAL".equals(values[1]))
return Double.class;
else if ("BLOB".equals(values[1]))
return Byte[].class;
}
return String.class;
}
return super.getColumnClass(col);
}
@Override
public boolean isCellEditable(int row, int col) {
if (col == 0)
return false;
else
return true;
}
};
final JTable table = new JTable(model) {
{
setRowSelectionAllowed(false);
setColumnSelectionAllowed(false);
}
String[] type_options = { "TEXT", "INTEGER", "REAL", "BLOB", "NULL" };
String[] oper_options = { "push", "pull" };
@SuppressWarnings("unchecked")
TableCellEditor[] editors = new TableCellEditor[] {
new DefaultCellEditor(new JComboBox(oper_options)) {
{
addCellEditorListener(new CellEditorListener() {
public void editingStopped(ChangeEvent e) {
if ("pull".equals(values[0])) {
model.setValueAt("TEXT", 1, 1);
}
}
public void editingCanceled(ChangeEvent e) {
}
});
}
},
new DefaultCellEditor(new JComboBox(type_options)),
null,
};
@Override
public TableCellEditor getCellEditor(int row, int col)
{
TableCellEditor editor = editors[row];
if (editor != null)
return editor;
else
return super.getCellEditor(row,col);
}
};
Object message = new Object[] {table};
showOptionDialog(relative, message,
String.format("Testing '%s'", name),
JOptionPane.DEFAULT_OPTION + Behavior.MODAL,
JOptionPane.PLAIN_MESSAGE,
null,
objects("Perform"), null,
new Function<Boolean>() {
public Boolean apply(Object... params) {
TableCellEditor editor = table.getCellEditor();
if (editor != null)
editor.stopCellEditing();
Object value = values[2];
if ("NULL".equals(values[1]))
value = null;
Object result = ScriptManager.doConversion(
value,
name,
values[0].toString(),
textArea.getText());
mess.setText(String.valueOf(result));
return false;
}
});
}
public static void main(String...args) {
BerichtsheftApp.loadSettings();
underTest = param("true", 0, args).equals("true");
int behavior = Behavior.MODAL;
if (underTest)
behavior |= Behavior.EXIT_ON_CLOSE;
new ScriptManager(null, null, null, null, null, null, behavior);
}
}